package thread;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

//阻塞队列
//在入队列的情况下，如果队列是满的时候呢，就会出现阻塞等待的问题，当出队列之后有空间后呢，才能继续入队
//在出队列的情况下，如果队列是空的时候呢，就会出现阻塞等待的问题，当入队列之后有元素的情况下，才能继续出队
//可以解决两个大问题：1、解耦合 2、削峰填谷
public class Demo22 {
    public static void main1(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new LinkedBlockingQueue<>(100);

        for (int i = 0;i < 100;i++) {
            queue.put("a");
        }
        System.out.println("队列现在是满的情况");

        queue.put("b");
        System.out.println("队列现在是满的情况下，是否还能入队列");
    }

    public static void main(String[] args) {
        //生产者消费者模型
        BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(1000);
        //put 和 take 添加 sleep 是为了 观看 队满和队空的两种特殊情况
        Thread producer = new Thread(() -> {
            int n = 0;
            while(true) {
                try {
                    queue.put(n);
                    System.out.println("生产元素" + n);
                    n++;
                    //这样添加 sleep 之后呢，消费就会和生产进行一起走，生产一个消费一个
                    //这样生产元素就是变得慢了，就等待消费者进行消费操作
                    //这样可以看到 队列空的情况
                    //Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"producer");

        Thread consumer = new Thread(() -> {
            while(true) {
                try {
                    Integer n = queue.take();
                    System.out.println("消费元素" + n);
                    //这样直接生产消费，就会非常的快，所以这里我们进行速度减少
                    //这样呢就是消费者慢，这回看到 队列满的情况
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"consumer");

        producer.start();
        consumer.start();
    }
}
